﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MethodWorx.Core.Mvc;
using MethodWorx.CMS.Content;
using MethodWorx.Core.DomainModel;
using MethodWorx.CMS.UI.Models;
using MethodWorx.CMS.UI.Models.Shared;
using MethodWorx.CMS.UI.Application;
using MethodWorx.CMS.UI.Application.ActionResults;
using MethodWorx.CMS.Administration;
using System.Net;
using System.IO;
using MethodWorx.CMS.Services;
using MethodWorx.CMS.Plugins;
using MethodWorx.CMS.Requests;
using MethodWorx.CMS.Configuration;
using MethodWorx.CMS.Membership;

namespace MethodWorx.CMS.UI.Controllers
{
    public class ContentController : ApplicationController
    {
        private SchemaService schema;
        private ContentService content;
        private ApplicationTypeService application;
        private PluginFactory pluginFactory;
        private UserService users;

        //
        // GET: /Content/
        public ContentController(SchemaService schema, ContentService content, ApplicationTypeService application , IPluginRepository plugins, UserService users)
        {
            this.schema = schema;
            this.content = content;
            this.application = application;
            this.users = users;

            this.pluginFactory = new PluginFactory(application.ApplicationSettingsRepository, plugins);
        }

        public ActionResult Index()
        {
            //
            //  ok, first of all seee if we have an application settings
            if(application.ApplicationSettingsRepository.FindSettings() == null)
            {
                //  we have no settings yet, so we have to set these up
                return View("SetupApplicationSettings");
            }
            return View(new ContentModel(this.content, Directory.GetFiles(Server.MapPath("~/App_Data/Macros")), this.CurrentUser));
        }

        private CreateRootPageModel CreateCreateRootPageModel()
        {
            var model = new CreateRootPageModel(this.schema);

            if (model.RootPageTemplate == null)
                throw new MethodWorx.CMS.UI.Application.WebException("Root Page Template Not Found");

            return model;
        }

        [HttpGet] 
        public JsonResult DeleteContentItem(ContentItem id)
        {
            if(id == null)
                throw new MethodWorx.CMS.UI.Application.WebException("Content Item Not Found");

            this.content.DeleteContentItem(id);

            return Json(new { success = true }, JsonRequestBehavior.AllowGet);
        }

        [HttpGet]
        public JsonResult DeletePage(Page id)
        {
            if (id == null)
                throw new MethodWorx.CMS.UI.Application.WebException("Page Not Found");

            this.content.DeletePage(id);

            return Json(new { success = true }, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public ActionResult CreatePage(string submit, Page parent, [Bind(Prefix = "pageBasicDetails")]PageBasicDetails pageBasicDetails)
        {/*
            if((submit ?? "").ToLower() == "create")
            {
                return RedirectToAction("Create", "PageTemplate", new { id = parent.Template.Id });
            }
            else if ((submit ?? "").ToLower() == "cancel")
                return new CloseDialogResult();
            else
            {
                if (ModelState.IsValid)
                {
                    content.CreatePage(parent, pageBasicDetails.Name, pageBasicDetails.Description, schema.GetPageTemplateById(pageBasicDetails.PageTemplate.Value));

                    //  close the window
                    return new CloseDialogResult()
                        .And(new RefreshContentResult());
                }
                else
                {
                    var model = this.CreateCreatePageModel(parent);
                    model.PageBasicDetails = pageBasicDetails;

                    return View(model);
                }
            }*/
            return null;
        }
    
        [HttpGet]
        public ActionResult CreateRootPage()
        {
            var model = this.CreateCreateRootPageModel();

            //
            //  ok, return the view
            return View(model);
        }

        [HttpPost]
        public ActionResult CreateRootPage(PageBasicDetails pageBasicDetails, string submit)
        {
            if ((submit ?? "").ToLower() == "create")
            {
                var model = this.CreateCreateRootPageModel();
                model.PageBasicDetails = pageBasicDetails;

                if (this.ModelState.IsValid)
                {
                    //
                    // ok, lets create
                    try
                    {
                        //  ok, create
                        this.content.CreateRootPage(pageBasicDetails.Name, pageBasicDetails.Description, schema.GetPageTemplateById(pageBasicDetails.PageTemplate.Value));
                        //  and return
                        return new RefreshContentResult()
                            .And(new CloseDialogResult());
                    }
                    catch (BusinessRuleException bre)
                    {
                        this.ModelState.AddModelError("Exception", bre.Message);
                        return View(model);
                    }


                }
                else
                    return View(model);
            }
            else
            {
                //  and return
                return new RefreshContentResult()
                    .And(new CloseDialogResult());
            }

        }

        [HttpGet]
        public JsonResult ContentStructure(Guid? pageId)
        {
            Page page = null;
            if (pageId == null)
            {
                page = this.content.GetRootPage();

                if (page != null)
                    return Json(new { attr = new { pageId = page.Id }, data = page.Name, state = "closed" }, JsonRequestBehavior.AllowGet);
                else
                    throw new MethodWorx.CMS.UI.Application.WebException("Page Not Found");
            }
            else
            {
                page = this.content.GetPageById(pageId.Value);
                var selected = page.ChildPages.Select(p =>
                        new
                        {
                            attr = new { pageId = p.Id },
                            data = p.Name,
                            state = "closed"
                        });
                return Json(selected.ToArray(), JsonRequestBehavior.AllowGet);
            }

            
        }

        [HttpGet]
        public JsonResult GetPagePreviewUrl(Guid id)
        {
            var page = this.content.GetPageById(id);
            if (page == null)
                return Json(new { success = false, message = "Page Not Found" });
            else
            {
                return Json(new { success = true, url = this.application.GetPagePreviewUrl(page) }, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpGet]
        public ActionResult Content(Guid id)
        {
            var page = this.content.GetPageById(id);
            if (page == null)
                throw new BusinessRuleException("Page not found");

            return View(new ConfigurePropertiesModel(page, 0, true, null));
        }

      
        [HttpPost]
        public JsonResult GetUrlsForPicker(string filter, string contextType, string contextId)
        {
            List<VirtualUrl> results = new List<VirtualUrl>();
            //
            //  get the virtual URLs for the url picker
            //  if we are at the root context
            if (contextType == null && contextId == null)
            {
                //
                //  this is the root of the site, so, this should just contain the available URLs on the system
                var rp = this.content.GetRootPage();
                if (rp != null)
                {
                    results.Add(new VirtualUrl()
                    {
                        Id = rp.Id.ToString(),
                        Name = rp.Name,
                        Type = "Page",
                        Path = rp.Path.TrimStart('/'),
                        IsFolder = false
                    });
                }

            }

            results.AddRange(this.pluginFactory.GetVirtualUrls(filter, contextType, contextId));

            foreach (var vr in results)
            {
                vr.Path = vr.Path.TrimStart('/');
            }

            return Json(results.Where(vu => string.IsNullOrEmpty(filter) || vu.Type.ToLower() == filter.ToLower()).ToArray());
        }

        [HttpGet]
        public ActionResult Edit(Guid id)
        {
            return View(new EditContentModel(this.content, id));
        }

        [HttpGet]
        public ActionResult EditContentItem(Guid id, Guid pageId)
        {
            var contentItem = this.content.GetContentItemById(id);
            var page = this.content.GetPageById(pageId);
            var model = new ConfigurePropertiesModel(contentItem, 0);
            model.Page = page;
            this.ViewData["pageId"] = pageId;
            return View("Properties", model);
        }

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult EditContentItem(Guid id, int? selectedPropertyIndex, PropertyDetails<object>[] propertyDetails, string command, Guid pageId)
        {
            //  get the page
            var contentItem = this.content.GetContentItemById(id);
            var page = this.content.GetPageById(pageId);
            //  and use it
            if (contentItem == null)
                throw new BusinessRuleException("Content item not found");

            var model = new ConfigurePropertiesModel(contentItem, selectedPropertyIndex ?? 0);
            model.Page = page;
            //model.Properties = propertyDetails ?? new PropertyDetails<object>[] { };
            foreach (var pd in propertyDetails)
            {
                var found = model.Properties.FirstOrDefault(p => p.Name == pd.Name);
                if (found != null)
                    ((ICustomPropertyDetails)found.Custom).CopyValueFrom((ICustomPropertyDetails)pd.Custom);
            }

            switch ((command ?? "").ToLower())
            {
                case "up":
                case "down":
                case "save":
                    if (this.ModelState.IsValid)
                    {
                        //
                        //  ok, we are valid, so lets save
                        this.content.UpdateContentItemProperties(id, model.Properties.Cast<IPropertyDetails>());
                        this.ViewData["message"] = "Properties were successfully saved";
                    }
                    break;
            }

            if ((command ?? "").ToLower() == "up")
            {
                //
                //  ok, take the content item
                this.content.ResequenceContent(contentItem.Page, contentItem, true);
                //return new AppJavaScriptResult("window.parent.location.href = window.parent.location.href");
            }

            if ((command ?? "").ToLower() == "down")
            {
                this.content.ResequenceContent(contentItem.Page, contentItem, false);
                //return new AppJavaScriptResult("window.parent.location.href = window.parent.location.href");
            }

            this.ViewData["pageId"] = pageId;
            return View("Properties", model);
        }

        public ActionResult Preview(Guid id)
        {
            Page page = this.content.GetPageById(id);
            if (page == null)
                throw new BusinessRuleException("Page not found");



            return View("Preview", new PreviewModel(this.users, this.application, page, (string)Session["PreviewSessionKey"], Request.Url.GetLeftPart(UriPartial.Authority) + Request.ApplicationPath));
        }


    }
}
